﻿using Jitter2.Collision;
using Jitter2.Collision.Shapes;

namespace Jitter2
{
    public class TriggerCollisionDetection(World world) : IBroadPhaseFilter
    {
        private readonly World world = world;

        public bool Filter(IDynamicTreeProxy shapeA, IDynamicTreeProxy shapeB)
        {
            if (shapeA is not RigidBodyShape sA || shapeB is not RigidBodyShape sB)
            {
                throw new World.InvalidCollisionTypeException(shapeA.GetType(), shapeB.GetType());
            }

            ref var b1 = ref sA.RigidBody.Data;
            ref var b2 = ref sB.RigidBody.Data;

            var isIgnoring = false;
            if (CollisionLayerRules.CollisionLayers.TryGetValue(b1.Layer.Layer + b2.Layer.Layer * 100, out var is_Ignoring))
                isIgnoring = is_Ignoring;
            var aLayer = b1.Layer.Layer;
            var bLayer = b2.Layer.Layer;
            if (IsLayerInMask(aLayer, b2.Layer.IncludeLayers) || IsLayerInMask(bLayer, b1.Layer.IncludeLayers))
                isIgnoring = false;
            if (IsLayerInMask(aLayer, b2.Layer.ExcludeLayers) || IsLayerInMask(bLayer, b1.Layer.ExcludeLayers))
                isIgnoring = true;
            if (isIgnoring)
                return false;

            if (!b1.IsTriggered && !b2.IsTriggered)
                return true;

            var colliding = NarrowPhase.MPREPA(sA, sB, b1.Orientation, b2.Orientation, b1.Position, b2.Position, out _, out _, out _, out _);
            if (colliding)
            {
                world.RegisterContact(sA.RigidBody.RigidBodyId, sB.RigidBody.RigidBodyId, sA.RigidBody, sB.RigidBody, default, default, default, 0);
            }

            return false;
        }

        public static bool IsLayerInMask(int layer, int mask)
        {
            return (mask & (1 << layer)) != 0; // 使用位运算检查层是否在掩码中
        }
    }
}
